home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / Screensavers / Moire / moire.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  32.6 KB  |  979 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Moire.cpp
  3. //
  4. // Desc: Fun screen saver
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #include <windows.h>
  9. #include <d3d8.h>
  10. #include <d3dx8.h>
  11. #include <stdio.h>
  12. #include <commdlg.h>
  13. #include <commctrl.h>
  14. #include "d3dsaver.h"
  15. #include "d3dfont.h"
  16. #include "Moire.h"
  17. #include "Resource.h"
  18. #include "dxutil.h"
  19.  
  20.  
  21. //-----------------------------------------------------------------------------
  22. // Name: struct MYVERTEX
  23. // Desc: D3D vertex type for this app
  24. //-----------------------------------------------------------------------------
  25. struct MYVERTEX
  26. {
  27.     D3DXVECTOR3 p;     // Position
  28.     FLOAT       tu;    // Vertex texture coordinates
  29.     FLOAT       tv;
  30.     
  31.     MYVERTEX(D3DXVECTOR3 pInit, FLOAT tuInit, FLOAT tvInit)
  32.         { p = pInit; tu = tuInit; tv = tvInit; }
  33. };
  34.  
  35. #define D3DFVF_MYVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
  36.  
  37.  
  38.  
  39. CMoireScreensaver* g_pMyMoireScreensaver = NULL;
  40.  
  41.  
  42.  
  43.  
  44. //-----------------------------------------------------------------------------
  45. // Name: WinMain()
  46. // Desc: Entry point to the program. Initializes everything, and goes into a
  47. //       message-processing loop. Idle time is used to render the scene.
  48. //-----------------------------------------------------------------------------
  49. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  50. {
  51.     HRESULT hr;
  52.     CMoireScreensaver moireSS;
  53.  
  54.     if( FAILED( hr = moireSS.Create( hInst ) ) )
  55.     {
  56.         moireSS.DisplayErrorMsg( hr );
  57.         return 0;
  58.     }
  59.  
  60.     return moireSS.Run();
  61. }
  62.  
  63.  
  64.  
  65.  
  66. //-----------------------------------------------------------------------------
  67. // Name: CMoireScreensaver()
  68. // Desc: Constructor
  69. //-----------------------------------------------------------------------------
  70. CMoireScreensaver::CMoireScreensaver( )
  71. {
  72.     g_pMyMoireScreensaver = this;
  73.  
  74.     InitCommonControls();
  75.  
  76.     ZeroMemory( m_DeviceObjectsArray, sizeof(m_DeviceObjectsArray) );
  77.  
  78.     srand(0);
  79.  
  80.     lstrcpy( m_strRegPath, TEXT("Software\\Microsoft\\Screensavers\\Moire") );
  81.     LoadString( NULL, IDS_DESCRIPTION, m_strWindowTitle, 200 );
  82.     m_dwMeshInterval = 30;
  83.     m_iMesh = -1;
  84.     Randomize( &m_iMesh, 3 );
  85.     m_iMeshPrev = -1;
  86.     m_fTimeNextMeshChange = 0.0f;
  87.     m_fTimeStartMeshChange = 0.0f;
  88.  
  89.     m_dwTextureInterval = 90;
  90.     m_iTexture = -1;
  91.     Randomize( &m_iTexture, 4 );
  92.     m_iTexturePrev = -1;
  93.     m_fTimeNextTextureChange = 0.0f;
  94.     m_fTimeStartTextureChange = 0.0f;
  95.  
  96.     m_dwColorInterval = 60;
  97.     m_iColorScheme = -1;
  98.     Randomize( &m_iColorScheme, 4 );
  99.     m_iColorSchemePrev = -1;
  100.     m_fTimeNextColorChange = 0.0f;
  101.     m_fTimeStartColorChange = 0.0f;
  102.     m_bBrightColors = TRUE;
  103.  
  104.     m_fSpeed = 1.0f;
  105. }
  106.  
  107.  
  108.  
  109.  
  110. //-----------------------------------------------------------------------------
  111. // Name: Randomize()
  112. // Desc: Find a random number between 0 and iMax that is different from the
  113. //       initial value of *piNum, and store it in *piNum.
  114. //-----------------------------------------------------------------------------
  115. VOID CMoireScreensaver::Randomize( INT* piNum, INT iMax )
  116. {
  117.     INT iInit = *piNum;
  118.     while ( *piNum == iInit )
  119.     {
  120.         *piNum = rand() % iMax;
  121.     }
  122. }
  123.  
  124.  
  125.  
  126.  
  127. //-----------------------------------------------------------------------------
  128. // Name: SetDevice()
  129. // Desc: 
  130. //-----------------------------------------------------------------------------
  131. VOID CMoireScreensaver::SetDevice( UINT iDevice )
  132. {
  133.     m_pDeviceObjects = &m_DeviceObjectsArray[iDevice];
  134. }
  135.  
  136.  
  137.  
  138.  
  139. //-----------------------------------------------------------------------------
  140. // Name: BuildMeshes()
  141. // Desc: 
  142. //-----------------------------------------------------------------------------
  143. HRESULT CMoireScreensaver::BuildMeshes()
  144. {
  145.     SAFE_RELEASE( m_pDeviceObjects->m_pVBArray[0] );
  146.     SAFE_RELEASE( m_pDeviceObjects->m_pVBArray[1] );
  147.     SAFE_RELEASE( m_pDeviceObjects->m_pVBArray[2] );
  148.  
  149.     // Sandwich
  150.     {
  151.         m_dwNumVerticesArray[0] = 12;
  152.  
  153.         if( FAILED( m_pd3dDevice->CreateVertexBuffer( m_dwNumVerticesArray[0] * sizeof(MYVERTEX),
  154.             D3DUSAGE_WRITEONLY, D3DFVF_MYVERTEX, D3DPOOL_MANAGED, &m_pDeviceObjects->m_pVBArray[0] ) ) )
  155.         {
  156.             return E_FAIL;
  157.         }
  158.  
  159.         MYVERTEX* v;
  160.         m_pDeviceObjects->m_pVBArray[0]->Lock( 0, 0, (BYTE**)&v, 0 );
  161.  
  162.         v[0] = MYVERTEX( D3DXVECTOR3(  10, -0.1f, -10 ),  0.0f,  0.0f );
  163.         v[1] = MYVERTEX( D3DXVECTOR3( -10, -0.1f, -10 ), 10.0f,  0.0f );
  164.         v[2] = MYVERTEX( D3DXVECTOR3(  10,  0.0f,  10 ),  0.0f, 10.0f );
  165.  
  166.         v[3] = MYVERTEX( D3DXVECTOR3( -10, -0.1f, -10 ), 10.0f,  0.0f );
  167.         v[4] = MYVERTEX( D3DXVECTOR3( -10,  0.0f,  10 ), 10.0f, 10.0f );
  168.         v[5] = MYVERTEX( D3DXVECTOR3(  10,  0.0f,  10 ),  0.0f, 10.0f );
  169.  
  170.         v[6] = MYVERTEX( D3DXVECTOR3( -10,  0.0f,  10 ),  0.0f, 10.0f );
  171.         v[7] = MYVERTEX( D3DXVECTOR3( -10,  0.1f, -10 ),  0.0f,  0.0f );
  172.         v[8] = MYVERTEX( D3DXVECTOR3(  10,  0.1f, -10 ), 10.0f,  0.0f );
  173.  
  174.         v[9] = MYVERTEX( D3DXVECTOR3(  10,  0.1f, -10 ), 10.0f,  0.0f );
  175.         v[10] = MYVERTEX( D3DXVECTOR3( 10,  0.0f,  10 ), 10.0f, 10.0f );
  176.         v[11] = MYVERTEX( D3DXVECTOR3(-10,  0.0f,  10 ),  0.0f, 10.0f );
  177.  
  178.         m_pDeviceObjects->m_pVBArray[0]->Unlock();
  179.     }
  180.     
  181.     // Wall
  182.     {
  183.         m_dwNumVerticesArray[1] = 6;
  184.         if( FAILED( m_pd3dDevice->CreateVertexBuffer( m_dwNumVerticesArray[1] * sizeof(MYVERTEX),
  185.             D3DUSAGE_WRITEONLY, D3DFVF_MYVERTEX, D3DPOOL_MANAGED, &m_pDeviceObjects->m_pVBArray[1] ) ) )
  186.         {
  187.             return E_FAIL;
  188.         }
  189.  
  190.         MYVERTEX* v;
  191.         m_pDeviceObjects->m_pVBArray[1]->Lock( 0, 0, (BYTE**)&v, 0 );
  192.  
  193.         v[0] = MYVERTEX( D3DXVECTOR3(  20, -20, 0.0f ), 10.0f, 10.0f );
  194.         v[1] = MYVERTEX( D3DXVECTOR3( -20, -20, 0.0f ),  0.0f, 10.0f );
  195.         v[2] = MYVERTEX( D3DXVECTOR3(  20,  20, 0.0f ), 10.0f,  0.0f );
  196.  
  197.         v[3] = MYVERTEX( D3DXVECTOR3( -20, -20, 0.0f ),  0.0f, 10.0f );
  198.         v[4] = MYVERTEX( D3DXVECTOR3( -20,  20, 0.0f ),  0.0f,  0.0f );
  199.         v[5] = MYVERTEX( D3DXVECTOR3(  20,  20, 0.0f ), 10.0f,  0.0f );
  200.  
  201.         m_pDeviceObjects->m_pVBArray[1]->Unlock();
  202.     }
  203.  
  204.     // Well
  205.     {
  206.         const INT NUM_SEGS = 48;
  207.         m_dwNumVerticesArray[2] = NUM_SEGS * 3;
  208.         if( FAILED( m_pd3dDevice->CreateVertexBuffer( m_dwNumVerticesArray[2] * sizeof(MYVERTEX),
  209.             D3DUSAGE_WRITEONLY, D3DFVF_MYVERTEX, D3DPOOL_MANAGED, &m_pDeviceObjects->m_pVBArray[2] ) ) )
  210.         {
  211.             return E_FAIL;
  212.         }
  213.  
  214.         MYVERTEX* v;
  215.         m_pDeviceObjects->m_pVBArray[2]->Lock( 0, 0, (BYTE**)&v, 0 );
  216.  
  217.         INT iVertex = 0;
  218.         FLOAT fTheta;
  219.         FLOAT fTheta2;
  220.         for( INT i = 0; i < NUM_SEGS; i++ )
  221.         {
  222.             fTheta  = (i+0) * (2 * D3DX_PI / NUM_SEGS);
  223.             fTheta2 = (i+1) * (2 * D3DX_PI / NUM_SEGS);
  224.             v[iVertex + 0] = MYVERTEX( D3DXVECTOR3(  10*cosf(fTheta),  10*sinf(fTheta),  -10.0f ),  5*cosf(fTheta),  5*sinf(fTheta) );
  225.             v[iVertex + 1] = MYVERTEX( D3DXVECTOR3(                 0,                0,  100.0f ),  0.0f,  0.0f );
  226.             v[iVertex + 2] = MYVERTEX( D3DXVECTOR3(  10*cosf(fTheta2), 10*sinf(fTheta2), -10.0f ),  5*cosf(fTheta2), 5*sinf(fTheta2) );
  227.  
  228.             iVertex += 3;
  229.         }
  230.  
  231.         m_pDeviceObjects->m_pVBArray[2]->Unlock();
  232.     }
  233.  
  234.     return S_OK;
  235. }
  236.  
  237.  
  238.  
  239.  
  240. //-----------------------------------------------------------------------------
  241. // Name: BuildTextures()
  242. // Desc: 
  243. //-----------------------------------------------------------------------------
  244. HRESULT CMoireScreensaver::BuildTextures()
  245. {
  246.     HRESULT hr;
  247.  
  248.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[0] );
  249.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[1] );
  250.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[2] );
  251.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[3] );
  252.  
  253.     if( FAILED( hr = LoadDDSTextureFromResource( m_pd3dDevice, 
  254.         MAKEINTRESOURCE(IDR_STRIPES_DDS), &m_pDeviceObjects->m_pTexArray[0] ) ) )
  255.     {
  256.         return hr;
  257.     }
  258.  
  259.     if( FAILED( hr = LoadDDSTextureFromResource( m_pd3dDevice, 
  260.         MAKEINTRESOURCE(IDR_BALL_DDS), &m_pDeviceObjects->m_pTexArray[1] ) ) )
  261.     {
  262.         return hr;
  263.     }
  264.  
  265.     if( FAILED( hr = LoadDDSTextureFromResource( m_pd3dDevice, 
  266.         MAKEINTRESOURCE(IDR_NOISE_DDS), &m_pDeviceObjects->m_pTexArray[2] ) ) )
  267.     {
  268.         return hr;
  269.     }
  270.  
  271.     if( FAILED( hr = LoadDDSTextureFromResource( m_pd3dDevice, 
  272.         MAKEINTRESOURCE(IDR_SPIRAL_DDS), &m_pDeviceObjects->m_pTexArray[3] ) ) )
  273.     {
  274.         return hr;
  275.     }
  276.  
  277.     return S_OK;
  278. }
  279.  
  280.  
  281.  
  282.  
  283. //-----------------------------------------------------------------------------
  284. // Name: LoadDDSTextureFromResource()
  285. // Desc: Note that this function asks D3DX to not create a full mip chain
  286. //       for the texture.  Modify the NumMips parameter to the
  287. //       D3DXCreateTextureFromFileInMemoryEx call if you want to reuse this
  288. //       function elsewhere and you do want a full mip chain for the texture.
  289. //-----------------------------------------------------------------------------
  290. HRESULT CMoireScreensaver::LoadDDSTextureFromResource( LPDIRECT3DDEVICE8 pd3dDevice, 
  291.     TCHAR* strRes, LPDIRECT3DTEXTURE8* ppTex )
  292. {
  293.     HRESULT hr;
  294.     HMODULE hModule = NULL;
  295.     HRSRC rsrc;
  296.     HGLOBAL hgData;
  297.     LPVOID pvData;
  298.     DWORD cbData;
  299.  
  300.     rsrc = FindResource( hModule, strRes, "DDS" );
  301.     if( rsrc != NULL )
  302.     {
  303.         cbData = SizeofResource( hModule, rsrc );
  304.         if( cbData > 0 )
  305.         {
  306.             hgData = LoadResource( hModule, rsrc );
  307.             if( hgData != NULL )
  308.             {
  309.                 pvData = LockResource( hgData );
  310.                 if( pvData != NULL )
  311.                 {
  312.                     if( FAILED( hr = D3DXCreateTextureFromFileInMemoryEx( 
  313.                         m_pd3dDevice, pvData, cbData, D3DX_DEFAULT, D3DX_DEFAULT, 
  314.                         1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_NONE, 
  315.                         D3DX_FILTER_NONE, 0, NULL, NULL, ppTex ) ) )
  316.                     {
  317.                         return hr;
  318.                     }
  319.                 }
  320.             }
  321.         }
  322.     }
  323.     
  324.     if( *ppTex == NULL)
  325.         return E_FAIL;
  326.  
  327.     return S_OK;
  328. }
  329.  
  330.  
  331.  
  332.  
  333. //-----------------------------------------------------------------------------
  334. // Name: FrameMove()
  335. // Desc: Called once per frame, the call is the entry point for animating
  336. //       the scene.
  337. //-----------------------------------------------------------------------------
  338. HRESULT CMoireScreensaver::FrameMove()
  339. {
  340.     D3DXCOLOR colBlack( 0, 0, 0, 0 );
  341.  
  342.     m_fScale1 = 2.0f * (1 + sinf(m_fTime * m_fSpeed / 20.0f));
  343.     m_fRot1 = 0.0f;
  344.  
  345.     m_fScale2 = 2.0f * (1 + sinf(m_fTime * m_fSpeed / 8.0f));
  346.     m_fRot2 = m_fTime * m_fSpeed * 0.025f;
  347.  
  348.     if( m_fTimeNextColorChange == 0.0f )
  349.     {
  350.         // Schedule next color scheme change
  351.         m_fTimeNextColorChange = m_fTime + m_dwColorInterval;
  352.     }
  353.     else if( m_fTimeNextColorChange < m_fTime )
  354.     {
  355.         // Start color scheme change
  356.         m_iColorSchemePrev = m_iColorScheme;
  357.         Randomize( &m_iColorScheme, 4 );
  358.         m_fTimeStartColorChange = m_fTime;
  359.         m_fTimeNextColorChange = 0.0f;
  360.     }
  361.     if( m_fTimeStartColorChange != 0.0f )
  362.     {
  363.         // Continue color scheme change
  364.         if( m_fTime > (m_fTimeStartColorChange + 1.0f) )
  365.         {
  366.             // Conclude color scheme change
  367.             m_fTimeStartColorChange = 0.0f;
  368.             m_iColorSchemePrev = -1;
  369.         }
  370.         else
  371.         {
  372.             // For first second after color change, do linear 
  373.             // transition from old to new color scheme
  374.             FLOAT fBeta = m_fTime - m_fTimeStartColorChange; // varies 0.0 to 1.0
  375.             D3DXCOLOR colOld1, colOld2, colOld3; // colors using old scheme
  376.             D3DXCOLOR colNew1, colNew2, colNew3; // colors using new scheme
  377.             GenerateColors( m_iColorSchemePrev, m_bBrightColors, &colOld1, &colOld2, &colOld3 );
  378.             GenerateColors( m_iColorScheme, m_bBrightColors, &colNew1, &colNew2, &colNew3 );
  379.             D3DXColorLerp( &m_col1, &colOld1, &colNew1, fBeta );
  380.             D3DXColorLerp( &m_col2, &colOld2, &colNew2, fBeta );
  381.             D3DXColorLerp( &m_col3, &colOld3, &colNew3, fBeta );
  382.         }
  383.     }
  384.     else
  385.     {
  386.         // No color scheme change is active, so compute colors as usual
  387.         GenerateColors( m_iColorScheme, m_bBrightColors, &m_col1, &m_col2, &m_col3 );
  388.     }
  389.  
  390.     if( m_fTimeNextTextureChange == 0.0f )
  391.     {
  392.         // Schedule next texture change
  393.         m_fTimeNextTextureChange = m_fTime + m_dwTextureInterval;
  394.     }
  395.     else if( m_fTimeNextTextureChange < m_fTime )
  396.     {
  397.         // Start texture change
  398.         m_iTexturePrev = m_iTexture;
  399.         m_fTimeStartTextureChange = m_fTime;
  400.         m_fTimeNextTextureChange = 0.0f;
  401.     }
  402.     if( m_fTimeStartTextureChange != 0.0f )
  403.     {
  404.         // Continue texture change
  405.         FLOAT fDelta = m_fTime - m_fTimeStartTextureChange; // varies 0.0 to 1.0
  406.  
  407.         // After 1 second, change textures if you haven't already
  408.         if( fDelta > 1.0f && m_iTexture == m_iTexturePrev)
  409.         {
  410.             Randomize( &m_iTexture, 4 );
  411.         }
  412.  
  413.         if( fDelta < 1.0f )
  414.         {
  415.             // For first second after change starts, fade colors from normal to black
  416.             D3DXColorLerp( &m_col1, &m_col1, &colBlack, fDelta );
  417.             D3DXColorLerp( &m_col2, &m_col2, &colBlack, fDelta );
  418.             D3DXColorLerp( &m_col3, &m_col3, &colBlack, fDelta );
  419.         }
  420.         else if( fDelta < 2.0f )
  421.         {
  422.             // For second second after change starts, just show black
  423.             m_col1 = colBlack;
  424.             m_col2 = colBlack;
  425.             m_col3 = colBlack;
  426.         }
  427.         else if( fDelta < 3.0f )
  428.         {
  429.             // For third second after change starts, fade colors from black to normal
  430.             D3DXColorLerp( &m_col1, &colBlack, &m_col1, fDelta - 2.0f );
  431.             D3DXColorLerp( &m_col2, &colBlack, &m_col2, fDelta - 2.0f );
  432.             D3DXColorLerp( &m_col3, &colBlack, &m_col3, fDelta - 2.0f );
  433.         }
  434.         else
  435.         {
  436.             // transition done
  437.             m_fTimeStartTextureChange = 0.0f;
  438.             m_iTexturePrev = -1;
  439.         }
  440.     }
  441.  
  442.     if( m_fTimeNextMeshChange == 0.0f )
  443.     {
  444.         // Schedule next mesh change
  445.         m_fTimeNextMeshChange = m_fTime + m_dwMeshInterval;
  446.     }
  447.     else if( m_fTimeNextMeshChange < m_fTime )
  448.     {
  449.         // Start mesh change
  450.         m_iMeshPrev = m_iMesh;
  451.         m_fTimeStartMeshChange = m_fTime;
  452.         m_fTimeNextMeshChange = 0.0f;
  453.     }
  454.     if( m_fTimeStartMeshChange != 0.0f )
  455.     {
  456.         // Continue mesh change
  457.         FLOAT fDelta = m_fTime - m_fTimeStartMeshChange;
  458.  
  459.         // After 1 second, change meshes if you haven't already
  460.         if( fDelta > 1.0f && m_iMesh == m_iMeshPrev)
  461.         {
  462.             Randomize( &m_iMesh, 3 );
  463.         }
  464.  
  465.         if( fDelta < 1.0f )
  466.         {
  467.             // For first second after change starts, fade colors from normal to black
  468.             D3DXColorLerp( &m_col1, &m_col1, &colBlack, fDelta );
  469.             D3DXColorLerp( &m_col2, &m_col2, &colBlack, fDelta );
  470.             D3DXColorLerp( &m_col3, &m_col3, &colBlack, fDelta );
  471.         }
  472.         else if( fDelta < 2.0f )
  473.         {
  474.             // For second second after change starts, just show black
  475.             m_col1 = colBlack;
  476.             m_col2 = colBlack;
  477.             m_col3 = colBlack;
  478.         }
  479.         else if( fDelta < 3.0f )
  480.         {
  481.             // For third second after change starts, fade colors from black to normal
  482.             D3DXColorLerp( &m_col1, &colBlack, &m_col1, fDelta - 2.0f );
  483.             D3DXColorLerp( &m_col2, &colBlack, &m_col2, fDelta - 2.0f );
  484.             D3DXColorLerp( &m_col3, &colBlack, &m_col3, fDelta - 2.0f );
  485.         }
  486.         else
  487.         {
  488.             // transition done
  489.             m_fTimeStartMeshChange = 0.0f;
  490.             m_iMeshPrev = -1;
  491.         }
  492.     }
  493.  
  494.     return S_OK;
  495. }
  496.  
  497.  
  498.  
  499.  
  500. //-----------------------------------------------------------------------------
  501. // Name: GenerateColors()
  502. // Desc: 
  503. //-----------------------------------------------------------------------------
  504. VOID CMoireScreensaver::GenerateColors( INT iColorScheme, BOOL bBright, 
  505.     D3DXCOLOR* pcol1, D3DXCOLOR* pcol2, D3DXCOLOR* pcol3 )
  506. {
  507.     FLOAT fWave1;
  508.     FLOAT fWave2;
  509.     FLOAT fConstant;
  510.  
  511.     if( bBright )
  512.     {
  513.         fWave1 = 1.0f * (1.0f + sinf(m_fTime))/2;
  514.         fWave2 = 0.5f * (1.0f + cosf(m_fTime))/2;
  515.         fConstant = 0.5f;
  516.     }
  517.     else
  518.     {
  519.         fWave1 = 0.50f + 0.50f * (1.0f + sinf(m_fTime))/2;
  520.         fWave2 = 0.25f + 0.25f * (1.0f + cosf(m_fTime))/2;
  521.         fConstant = 0.375f;
  522.     }
  523.  
  524.     switch( iColorScheme )
  525.     {
  526.     case 0:
  527.         *pcol1 = D3DXCOLOR( fWave1, fWave2, 0.0f, 1.0f );
  528.         *pcol2 = D3DXCOLOR( fWave2, fWave1, 0.0f, 1.0f );
  529.         *pcol3 = D3DXCOLOR( 0.0f, 0.0f, fConstant, 1.0f );
  530.         break;
  531.  
  532.     case 1:
  533.         *pcol1 = D3DXCOLOR( 0.0f, fWave1, fWave2, 1.0f );
  534.         *pcol2 = D3DXCOLOR( 0.0f, fWave2, fWave1, 1.0f );
  535.         *pcol3 = D3DXCOLOR( fConstant, 0.0f, 0.0f, 1.0f );
  536.         break;
  537.  
  538.     case 2:
  539.         *pcol1 = D3DXCOLOR( fWave1, 0.0f, fWave2, 1.0f );
  540.         *pcol2 = D3DXCOLOR( fWave2, 0.0f, fWave1, 1.0f );
  541.         *pcol3 = D3DXCOLOR( 0.0f, fConstant, 0.0f, 1.0f );
  542.         break;
  543.  
  544.     case 3:
  545.         *pcol1 = D3DXCOLOR( fWave1, fWave1, fWave1, 1.0f );
  546.         *pcol2 = D3DXCOLOR( fWave2, fWave2, fWave2, 1.0f );
  547.         *pcol3 = D3DXCOLOR( 0.0f, 0.0f, 0.0f, 1.0f );
  548.         break;
  549.     }
  550. }
  551.  
  552.  
  553.  
  554.  
  555. //-----------------------------------------------------------------------------
  556. // Name: Render()
  557. // Desc: Called once per frame, the call is the entry point for 3d
  558. //       rendering. This function sets up render states, clears the
  559. //       viewport, and renders the scene.
  560. //-----------------------------------------------------------------------------
  561. HRESULT CMoireScreensaver::Render()
  562. {
  563.     D3DXMATRIX mat1;
  564.     D3DXMATRIX mat2;
  565.     D3DXMATRIX mat3;
  566.  
  567.     SetProjectionMatrix( 0.05f, 120.0f );
  568.  
  569.     m_pd3dDevice->SetTexture(0, m_pDeviceObjects->m_pTexArray[m_iTexture] );
  570.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  571.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  572.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  573.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  574.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );
  575.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  576.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  577. //    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
  578.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,  D3DTADDRESS_WRAP );
  579.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,  D3DTADDRESS_WRAP );
  580.     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
  581.  
  582.     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING,            TRUE );
  583.     m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,    TRUE );
  584.     m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,            D3DBLEND_SRCALPHA );
  585.     m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,           D3DBLEND_ONE );
  586.  
  587.     HRESULT hr;
  588.     DWORD dw;
  589.     hr = m_pd3dDevice->ValidateDevice(&dw);
  590.  
  591.     m_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX );
  592.     m_pd3dDevice->SetStreamSource( 0, m_pDeviceObjects->m_pVBArray[m_iMesh], sizeof(MYVERTEX) );
  593.  
  594.     // Clear the viewport
  595.     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, m_col3, 1.0f, 0L );
  596.  
  597.     // Begin the scene 
  598.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  599.     {
  600.  
  601.         D3DXMatrixScaling( &mat1, m_fScale1, m_fScale1, 1.0 );
  602.         D3DXMatrixRotationZ( &mat2, m_fRot1 );
  603.         D3DXMatrixMultiply( &mat3, &mat1, &mat2 );
  604.         m_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat3 );
  605. //        m_pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, m_col1 );
  606.         D3DMATERIAL8 mtrl;
  607.         mtrl.Diffuse = m_col1;
  608.         mtrl.Ambient = m_col1;
  609.         mtrl.Specular = m_col1;
  610.         mtrl.Emissive = m_col1;
  611.         mtrl.Power = 0;
  612.         m_pd3dDevice->SetMaterial(&mtrl);
  613.  
  614.         m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, m_dwNumVerticesArray[m_iMesh] / 3 );
  615.  
  616.         D3DXMatrixScaling( &mat1, m_fScale2, m_fScale2, 1.0 );
  617.         D3DXMatrixRotationZ( &mat2, m_fRot2 );
  618.         D3DXMatrixMultiply( &mat3, &mat1, &mat2 );
  619.         m_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat3 );
  620. //        m_pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, m_col2 );
  621.         mtrl.Diffuse = m_col2;
  622.         mtrl.Ambient = m_col2;
  623.         mtrl.Specular = m_col2;
  624.         mtrl.Emissive = m_col2;
  625.         mtrl.Power = 0;
  626.         m_pd3dDevice->SetMaterial(&mtrl);
  627.  
  628.         m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, m_dwNumVerticesArray[m_iMesh] / 3 );
  629.  
  630.         // Show frame rate
  631.         m_pDeviceObjects->m_pStatsFont->DrawText( 3,  1, D3DCOLOR_ARGB(255,0,0,0), m_strFrameStats );
  632.         m_pDeviceObjects->m_pStatsFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  633.  
  634.         m_pDeviceObjects->m_pStatsFont->DrawText( 3, 21, D3DCOLOR_ARGB(255,0,0,0), m_strDeviceStats );
  635.         m_pDeviceObjects->m_pStatsFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  636.  
  637.         // End the scene.
  638.         m_pd3dDevice->EndScene();
  639.     }
  640.  
  641.     return S_OK;
  642. }
  643.  
  644.  
  645.  
  646.  
  647. //-----------------------------------------------------------------------------
  648. // Name: RestoreDeviceObjects()
  649. // Desc: 
  650. //-----------------------------------------------------------------------------
  651. HRESULT CMoireScreensaver::RestoreDeviceObjects()
  652. {
  653.     if( m_pd3dDevice == NULL )
  654.         return S_OK;
  655.     
  656.     // Set up sensible projection and view matrices
  657.     D3DXMATRIX  view;
  658.     D3DXMatrixLookAtLH( &view , &D3DXVECTOR3(0,0,-10) , &D3DXVECTOR3(0,0,0) , &D3DXVECTOR3(0,1,0) );
  659.     m_pd3dDevice->SetTransform( D3DTS_VIEW , &view );
  660.  
  661.     // Set some basic renderstates
  662.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE , TRUE );
  663.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE , FALSE );
  664.  
  665.     if( FAILED( BuildMeshes() ) )
  666.         return E_FAIL;
  667.  
  668.     if( FAILED( BuildTextures() ) )
  669.         return E_FAIL;
  670.  
  671.     m_pDeviceObjects->m_pStatsFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  672.     m_pDeviceObjects->m_pStatsFont->InitDeviceObjects( m_pd3dDevice );
  673.     m_pDeviceObjects->m_pStatsFont->RestoreDeviceObjects();
  674.  
  675.     return S_OK;
  676. }
  677.  
  678.  
  679.  
  680.  
  681. //-----------------------------------------------------------------------------
  682. // Name: InvalidateDeviceObjects()
  683. // Desc: 
  684. //-----------------------------------------------------------------------------
  685. HRESULT CMoireScreensaver::InvalidateDeviceObjects()
  686. {
  687.     m_pDeviceObjects->m_pStatsFont->InvalidateDeviceObjects();
  688.     m_pDeviceObjects->m_pStatsFont->DeleteDeviceObjects();
  689.     SAFE_DELETE( m_pDeviceObjects->m_pStatsFont );
  690.  
  691.     SAFE_RELEASE( m_pDeviceObjects->m_pVBArray[0] );
  692.     SAFE_RELEASE( m_pDeviceObjects->m_pVBArray[1] );
  693.     SAFE_RELEASE( m_pDeviceObjects->m_pVBArray[2] );
  694.  
  695.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[0] );
  696.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[1] );
  697.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[2] );
  698.     SAFE_RELEASE( m_pDeviceObjects->m_pTexArray[3] );
  699.  
  700.     return S_OK;
  701. }
  702.  
  703.  
  704.  
  705.  
  706. //-----------------------------------------------------------------------------
  707. // Name: ReadSettings()
  708. // Desc: 
  709. //-----------------------------------------------------------------------------
  710. VOID CMoireScreensaver::ReadSettings()
  711. {
  712.     ReadRegistry();
  713. }
  714.  
  715.  
  716.  
  717.  
  718. //-----------------------------------------------------------------------------
  719. // Name: ConfigureDialogProcHelper()
  720. // Desc: 
  721. //-----------------------------------------------------------------------------
  722. INT_PTR CALLBACK ConfigureDialogProcHelper( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  723. {
  724.     return g_pMyMoireScreensaver->ConfigureDialogProc( hwndDlg, uMsg, wParam, lParam );
  725. }
  726.  
  727.  
  728.  
  729.  
  730. //-----------------------------------------------------------------------------
  731. // Name: DoConfig()
  732. // Desc: 
  733. //-----------------------------------------------------------------------------
  734. VOID CMoireScreensaver::DoConfig()
  735. {
  736.     DialogBox( NULL, MAKEINTRESOURCE(IDD_CONFIGURE), m_hWndParent, ConfigureDialogProcHelper );
  737. }
  738.  
  739.  
  740.  
  741.  
  742. //-----------------------------------------------------------------------------
  743. // Name: ConfigureDialogProc()
  744. // Desc: 
  745. //-----------------------------------------------------------------------------
  746. INT_PTR CALLBACK CMoireScreensaver::ConfigureDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  747. {
  748.     HWND hwndSpeed = GetDlgItem( hwndDlg, IDC_SPEED );
  749.     HWND hwndIntense = GetDlgItem( hwndDlg, IDC_INTENSE );
  750.     HWND hwndPastel = GetDlgItem( hwndDlg, IDC_PASTEL );
  751.     HWND hwndColorInterval = GetDlgItem( hwndDlg, IDC_COLORINTERVAL );
  752.     HWND hwndTextureInterval = GetDlgItem( hwndDlg, IDC_TEXTUREINTERVAL );
  753.     HWND hwndMeshInterval = GetDlgItem( hwndDlg, IDC_MESHINTERVAL );
  754.     TCHAR sz[10];
  755.     DWORD iSpeed;
  756.  
  757.     switch (uMsg)
  758.     {
  759.     case WM_INITDIALOG:
  760.         WriteRegistry();
  761.         SendMessage(hwndSpeed, TBM_SETRANGE, FALSE, MAKELONG(0, 5));
  762.         if( m_fSpeed == 0.25f )
  763.             SendMessage(hwndSpeed, TBM_SETPOS, TRUE, 0);
  764.         else if( m_fSpeed == 0.5f )
  765.             SendMessage(hwndSpeed, TBM_SETPOS, TRUE, 1);
  766.         else if( m_fSpeed == 0.75f )
  767.             SendMessage(hwndSpeed, TBM_SETPOS, TRUE, 2);
  768.         else if( m_fSpeed == 1.0f )
  769.             SendMessage(hwndSpeed, TBM_SETPOS, TRUE, 3);
  770.         else if( m_fSpeed == 1.5f )
  771.             SendMessage(hwndSpeed, TBM_SETPOS, TRUE, 4);
  772.         else if( m_fSpeed == 2.0f )
  773.             SendMessage(hwndSpeed, TBM_SETPOS, TRUE, 5);
  774.  
  775.         if( m_bBrightColors )
  776.             CheckRadioButton( hwndDlg, IDC_INTENSE, IDC_PASTEL, IDC_INTENSE );
  777.         else
  778.             CheckRadioButton( hwndDlg, IDC_INTENSE, IDC_PASTEL, IDC_PASTEL );
  779.  
  780.         wsprintf(sz, TEXT("%d"), m_dwColorInterval);
  781.         SetWindowText(hwndColorInterval, sz);
  782.  
  783.         wsprintf(sz, TEXT("%d"), m_dwTextureInterval);
  784.         SetWindowText(hwndTextureInterval, sz);
  785.  
  786.         wsprintf(sz, TEXT("%d"), m_dwMeshInterval);
  787.         SetWindowText(hwndMeshInterval, sz);
  788.         return TRUE;
  789.  
  790.     case WM_COMMAND:
  791.         switch( LOWORD( wParam ) )
  792.         {
  793.         case IDC_COLORINTERVAL:
  794.             if( HIWORD( wParam ) == EN_CHANGE )
  795.             {
  796.                 m_fTimeNextColorChange = 0.0f;
  797.                 GetWindowText(hwndColorInterval, sz, 10);
  798.                 sscanf(sz, TEXT("%d"), &m_dwColorInterval);
  799.             }
  800.             break;
  801.  
  802.         case IDC_MESHINTERVAL:
  803.             if( HIWORD( wParam ) == EN_CHANGE )
  804.             {
  805.                 m_fTimeNextMeshChange = 0.0f;
  806.                 GetWindowText(hwndMeshInterval, sz, 10);
  807.                 sscanf(sz, TEXT("%d"), &m_dwMeshInterval);
  808.             }
  809.             break;
  810.  
  811.         case IDC_TEXTUREINTERVAL:
  812.             if( HIWORD( wParam ) == EN_CHANGE )
  813.             {
  814.                 m_fTimeNextTextureChange = 0.0f;
  815.                 GetWindowText(hwndTextureInterval, sz, 10);
  816.                 sscanf(sz, TEXT("%d"), &m_dwTextureInterval);
  817.             }
  818.             break;
  819.  
  820.         case IDC_SCREENSETTINGS:
  821.             DoScreenSettingsDialog( hwndDlg );
  822.             break;
  823.  
  824.         case IDOK:
  825.             m_bBrightColors = ( IsDlgButtonChecked( hwndDlg, IDC_INTENSE ) == BST_CHECKED );
  826.             iSpeed = (DWORD)SendMessage( hwndSpeed, TBM_GETPOS, 0, 0 );
  827.             if( iSpeed == 0 )
  828.                 m_fSpeed = 0.25f;
  829.             else if( iSpeed == 1 )
  830.                 m_fSpeed = 0.5f;
  831.             else if( iSpeed == 2 )
  832.                 m_fSpeed = 0.75f;
  833.             else if( iSpeed == 3 )
  834.                 m_fSpeed = 1.0f;
  835.             else if( iSpeed == 4 )
  836.                 m_fSpeed = 1.5f;
  837.             else if( iSpeed == 5 )
  838.                 m_fSpeed = 2.0f;
  839.             WriteRegistry(); // save new settings
  840.             EndDialog(hwndDlg, IDOK);
  841.             break;
  842.  
  843.         case IDCANCEL:
  844.             ReadRegistry(); // restore previous settings
  845.             EndDialog(hwndDlg, IDCANCEL);
  846.             break;
  847.         }
  848.         return TRUE;
  849.     
  850.     default:
  851.         return FALSE;
  852.     }
  853. }
  854.  
  855.  
  856.  
  857.  
  858. //-----------------------------------------------------------------------------
  859. // Name: ReadRegistry()
  860. // Desc: 
  861. //-----------------------------------------------------------------------------
  862. HRESULT CMoireScreensaver::ReadRegistry()
  863. {
  864.     HKEY hkey;
  865.     DWORD dwType = REG_DWORD;
  866.     DWORD dwLength = sizeof(DWORD);
  867.  
  868.     if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath, 
  869.         0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
  870.     {
  871.         RegQueryValueEx( hkey, TEXT("Bright Colors"), NULL, &dwType, (BYTE*)&m_bBrightColors, &dwLength );
  872.  
  873.         RegQueryValueEx( hkey, TEXT("Mesh"), NULL, &dwType, (BYTE*)&m_iMesh, &dwLength);
  874.         if( m_iMesh < 0 )
  875.             m_iMesh = 0;
  876.         else if( m_iMesh > 2 )
  877.             m_iMesh = 2;
  878.  
  879.         RegQueryValueEx( hkey, TEXT("Texture"), NULL, &dwType, (BYTE*)&m_iTexture, &dwLength);
  880.         if( m_iTexture < 0 )
  881.             m_iTexture = 0;
  882.         else if( m_iTexture > 3 )
  883.             m_iTexture = 3;
  884.  
  885.         RegQueryValueEx( hkey, TEXT("Color Scheme"), NULL, &dwType, (BYTE*)&m_iColorScheme, &dwLength);
  886.         if( m_iColorScheme < 0 )
  887.             m_iColorScheme = 0;
  888.         else if( m_iColorScheme > 3 )
  889.             m_iColorScheme = 3;
  890.  
  891.         DWORD iSpeed;
  892.         RegQueryValueEx( hkey, TEXT("Speed"), NULL, &dwType, (BYTE*)&iSpeed, &dwLength);
  893.         if( iSpeed > 5 )
  894.             iSpeed = 5;
  895.  
  896.         if( iSpeed == 0 )
  897.             m_fSpeed = 0.25f;
  898.         else if( iSpeed == 1 )
  899.             m_fSpeed = 0.5f;
  900.         else if( iSpeed == 2 )
  901.             m_fSpeed = 0.75f;
  902.         else if( iSpeed == 3 )
  903.             m_fSpeed = 1.0f;
  904.         else if( iSpeed == 4 )
  905.             m_fSpeed = 1.5f;
  906.         else if( iSpeed == 5 )
  907.             m_fSpeed = 2.0f;
  908.  
  909.         RegQueryValueEx( hkey, TEXT("Mesh Interval"), NULL, &dwType, (BYTE*)&m_dwMeshInterval, &dwLength);
  910.         if( m_dwMeshInterval > 9999 )
  911.             m_dwMeshInterval = 9999;
  912.  
  913.         RegQueryValueEx( hkey, TEXT("Color Interval"), NULL, &dwType, (BYTE*)&m_dwColorInterval, &dwLength);
  914.         if( m_dwColorInterval > 9999 )
  915.             m_dwColorInterval = 9999;
  916.  
  917.         RegQueryValueEx( hkey, TEXT("Texture Interval"), NULL, &dwType, (BYTE*)&m_dwTextureInterval, &dwLength);
  918.         if( m_dwTextureInterval > 9999 )
  919.             m_dwTextureInterval = 9999;
  920.  
  921.         ReadScreenSettings( hkey );
  922.  
  923.         RegCloseKey( hkey );
  924.     }
  925.  
  926.     return S_OK;
  927. }
  928.  
  929.  
  930.  
  931.  
  932. //-----------------------------------------------------------------------------
  933. // Name: WriteRegistry()
  934. // Desc: 
  935. //-----------------------------------------------------------------------------
  936. HRESULT CMoireScreensaver::WriteRegistry()
  937. {
  938.     HKEY hkey;
  939.  
  940.     if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath, 
  941.         0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
  942.     {
  943.         RegSetValueEx( hkey, TEXT("Bright Colors"), NULL, REG_DWORD, (BYTE*)&m_bBrightColors, sizeof(DWORD) );
  944.  
  945.         RegSetValueEx( hkey, TEXT("Mesh"), NULL, REG_DWORD, (BYTE*)&m_iMesh, sizeof(DWORD) );
  946.  
  947.         RegSetValueEx( hkey, TEXT("Texture"), NULL, REG_DWORD, (BYTE*)&m_iTexture, sizeof(DWORD));
  948.  
  949.         RegSetValueEx( hkey, TEXT("Color Scheme"), NULL, REG_DWORD, (BYTE*)&m_iColorScheme, sizeof(DWORD));
  950.  
  951.         DWORD iSpeed;
  952.         if( m_fSpeed == 0.25f )
  953.             iSpeed = 0;
  954.         else if( m_fSpeed == 0.5f )
  955.             iSpeed = 1;
  956.         else if( m_fSpeed == 0.75f )
  957.             iSpeed = 2;
  958.         else if( m_fSpeed == 1.0f )
  959.             iSpeed = 3;
  960.         else if( m_fSpeed == 1.5f )
  961.             iSpeed = 4;
  962.         else if( m_fSpeed == 2.0f )
  963.             iSpeed = 5;
  964.         RegSetValueEx( hkey, TEXT("Speed"), NULL, REG_DWORD, (BYTE*)&iSpeed, sizeof(DWORD));
  965.  
  966.         RegSetValueEx( hkey, TEXT("Mesh Interval"), NULL, REG_DWORD, (BYTE*)&m_dwMeshInterval, sizeof(DWORD));
  967.  
  968.         RegSetValueEx( hkey, TEXT("Color Interval"), NULL, REG_DWORD, (BYTE*)&m_dwColorInterval, sizeof(DWORD));
  969.  
  970.         RegSetValueEx( hkey, TEXT("Texture Interval"), NULL, REG_DWORD, (BYTE*)&m_dwTextureInterval, sizeof(DWORD));
  971.  
  972.         WriteScreenSettings( hkey );
  973.  
  974.         RegCloseKey( hkey );
  975.     }
  976.  
  977.     return S_OK;
  978. }
  979.